#include "dask.h"
using namespace std;
DiskArm::DiskArm() {
    int i;
    std::cout << "Please input Current cylinder: ";
std::cin >> CurrentCylinder;

//磁头方向
// 0 ：向小磁道号方向移动
// 1 ：向大磁道号方向移动
    std::cout << "Please input Current Direction (0/1): ";
std::cin >> SeekDirection;

//输入磁盘请求数，请求道号
    std::cout << "Please input Request Numbers: ";
    std::cin >> RequestNumber;
    std::cout << "Please input Request cylinder string: ";
    Request = new int[RequestNumber];
    Cylinder = new int[RequestNumber];
    for (i = 0; i < RequestNumber; i++) {
        std::cin >> Request[i];
    }
}

DiskArm::~DiskArm() {
    delete[] Request;
    delete[] Cylinder;
}

//初始化道号，寻道记录
void DiskArm::InitSpace(char *MethodName) {
    int i;
    std::cout << std::endl << MethodName << std::endl;
    SeekNumber = 0;
    SeekChang = 0;
    for (i = 0; i < RequestNumber; i++) {
        Cylinder[i] = Request[i];
    }
}

//统计报告算法执⾏情况
void DiskArm::Report(void) {
    std::cout << std::endl;
    std::cout << "Seek Number: " << SeekNumber << std::endl;
    std::cout << "Change Direction: " << SeekChang << std::endl << std::endl;
}

void DiskArm::Fcfs(void) {
    int Current = CurrentCylinder;
    int Direction = SeekDirection;
    InitSpace("FCFS");
    std::cout << Current;
    for (int i = 0; i < RequestNumber; i++) {
        if (((Cylinder[i] >= Current) && !Direction) || ((Cylinder[i] < Current) && Direction)) {
            SeekChang++;
            Direction = !Direction; //调头数加1

            //报告当前响应的道号
            std::cout << std::endl << Current << " -> " << Cylinder[i];
        } else {
            //不需要调头，报告当前响应的道号
            std::cout << " -> " << Cylinder[i];
        }

        //累计寻道数，响应过的道号变为当前道号
        SeekNumber += abs(Current - Cylinder[i]);
        Current = Cylinder[i];
}
//报告磁盘调度情况
    Report();
}

void DiskArm::Sstf(void) {
    int Shortest;
    int Distance = 999999;
    int Direction = SeekDirection;
    int Current = CurrentCylinder;
    InitSpace("SSTF");
    std::cout << Current;
    for (int i = 0; i < RequestNumber; i++) {
        for (int j = 0; j < RequestNumber; j++) {
            if (Cylinder[j] == -1) continue;
            if (Distance > abs(Current - Cylinder[j])) {
                Distance = abs(Current - Cylinder[j]);
                Shortest = j;
            }
        }
        if (((Cylinder[Shortest] >= Current) && !Direction) || ((Cylinder[Shortest] < Current) && Direction)) {
            SeekChang++;
            Direction = !Direction;
            std::cout << std::endl << Current << " -> " << Cylinder[Shortest];
        } else {
            std::cout << " -> " << Cylinder[Shortest];
        }
        SeekNumber += abs(Current - Cylinder[Shortest]);
        Current = Cylinder[Shortest];
        Distance = 999999;
        Cylinder[Shortest] = -1;
    }
    Report();
}

void DiskArm::Scan(void) {
    int NextCylinder;
    int Direction = SeekDirection; // 当前移动方向
    int Current = CurrentCylinder; // 磁盘臂当前位置
    int RequestCount = RequestNumber; // 待处理请求数
    InitSpace("SCAN"); // 初始化用于报告的空间
    std::cout << Current; // 报告当前位置
    while (RequestCount > 0) { // 继续直到所有请求都被服务完
        if (Direction) { // 向较高柱面号移动
            NextCylinder = INT_MAX;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] >= Current && Cylinder[j] < NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        } else { // 向较低柱面号移动
            NextCylinder = INT_MIN;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] <= Current && Cylinder[j] > NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        }
        // 报告下一个待服务的柱面号
        if (NextCylinder != Current) {
            std::cout << " -> " << NextCylinder;
        }
        // 更新总寻道距离
        SeekNumber += abs(Current - NextCylinder);
        // 将磁盘臂移动到下一个柱面
        Current = NextCylinder;

        if (NextCylinder == INT_MAX || NextCylinder == INT_MIN) { // 当前方向没有请求
            Direction = !Direction; // 反转方向
            SeekChang++;
            std::cout<<endl;
            continue;
        }
        // 标记已服务的请求
        for (int j = 0; j < RequestNumber; j++) {
            if (Cylinder[j] == NextCylinder) {
                Cylinder[j] = -1;
                RequestCount--; // 减少待处理请求计数
                break;
            }
        }
    }

    Report(); // 报告磁盘臂调度的摘要信息
}

void DiskArm::CScan(void) {
    int NextCylinder;
    int Direction = SeekDirection; // 当前移动方向
    int Current = CurrentCylinder; // 磁盘臂当前位置
    int RequestCount = RequestNumber; // 待处理请求数
    InitSpace("CSCAN"); // 初始化用于报告的空间
    std::cout << Current; // 报告当前位置
    while (RequestCount > 0) { // 继续直到所有请求都被服务完
        if (Direction) { // 向较高柱面号移动
            NextCylinder = INT_MAX;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] >= Current && Cylinder[j] < NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        } else { // 向较低柱面号移动
            NextCylinder = INT_MIN;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] <= Current && Cylinder[j] > NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        }
        // 报告下一个待服务的柱面号
        if (NextCylinder != Current) {
            std::cout << " -> " << NextCylinder;
        }
        // 更新总寻道距离
        SeekNumber += abs(Current - NextCylinder);
        // 将磁盘臂移动到下一个柱面
        Current = NextCylinder;

        if (NextCylinder == INT_MAX || NextCylinder == INT_MIN) { // 当前方向没有请求
            Direction = !Direction; // 反转方向
            SeekChang++;
            std::cout<<endl;
            if(NextCylinder==INT_MAX){
                Current=INT_MIN;
                SeekNumber+=(INT_MAX-INT_MIN);
                Direction = !Direction; // 反转方向
                SeekChang++;
                std::cout<<INT_MAX<<" -> "<<INT_MIN<<endl;
            }
            if(NextCylinder==INT_MIN){
                Current=INT_MAX;
                SeekNumber+=(INT_MAX-INT_MIN);
                Direction = !Direction; // 反转方向
                SeekChang++;
                std::cout<<INT_MIN<<" -> "<<INT_MAX<<endl;
            }
            continue;
        }
        // 标记已服务的请求
        for (int j = 0; j < RequestNumber; j++) {
            if (Cylinder[j] == NextCylinder) {
                Cylinder[j] = -1;
                RequestCount--; // 减少待处理请求计数
                break;
            }
        }
    }

    Report(); // 报告磁盘臂调度的摘要信息
}

void DiskArm::Look(void) {
    int NextCylinder;
    int Direction = SeekDirection; // 当前移动方向
    int Current = CurrentCylinder; // 磁盘臂当前位置
    int RequestCount = RequestNumber; // 待处理请求数
    InitSpace("LOOK"); // 初始化用于报告的空间
    std::cout << Current; // 报告当前位置
    while (RequestCount > 0) { // 继续直到所有请求都被服务完
        if (Direction) { // 向较高柱面号移动
            NextCylinder = INT_MAX;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] >= Current && Cylinder[j] < NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        } else { // 向较低柱面号移动
            NextCylinder = INT_MIN;
            for (int j = 0; j < RequestNumber; j++) {
                if (Cylinder[j] != -1 && Cylinder[j] <= Current && Cylinder[j] > NextCylinder) {
                    NextCylinder = Cylinder[j];
                }
            }
        }

        if (NextCylinder == INT_MAX || NextCylinder == INT_MIN) { // 当前方向没有请求
            Direction = !Direction; // 反转方向
            SeekChang++;
            std::cout<<endl;
            continue;
        }

        // 报告下一个待服务的柱面号
        if (NextCylinder != Current) {
            std::cout << " -> " << NextCylinder;
        }
        // 更新总寻道距离
        SeekNumber += abs(Current - NextCylinder);
        // 将磁盘臂移动到下一个柱面
        Current = NextCylinder;

        // 标记已服务的请求
        for (int j = 0; j < RequestNumber; j++) {
            if (Cylinder[j] == NextCylinder) {
                Cylinder[j] = -1;
                RequestCount--; // 减少待处理请求计数
                break;
            }
        }
    }

    Report(); // 报告磁盘臂调度的摘要信息
}

int main(int argc, char *argv[]) {
    DiskArm *dask = new DiskArm();
    dask->Fcfs();
    dask->Sstf();
    dask->Scan();
    dask->CScan();
    dask->Look();
}
